#include <stdatomic.h>

#include "elements/elements.h"
#include "elements/amm.h"
#include <stdio.h>

#include "as_entity.h"
#include "dbsm.h"
#include "gsg.h"
#include "rdf.h"
#include "services/dashboard.h"
#include "services/input.h"

#define LOCAL_IPV6 "::1"

atomic_int exit_flag = 0; //C11
bool direct_snp = FALSE;
bool is_dashboard = FALSE;

size_t elements_count = 5;
net_element_t elements[] = {
    {
        .SAC = 2,
        .element_type = ELEMENT_AMM,
        .element_tag = "AMM",
        .start_func = start_amm,
        .stop_func = stop_amm,
        .client_interface_count = 1,
        .client_interfaces = {
            {
                .meta = {
                    .interface_type = INTERFACE_G3,
                },
                .peer_SAC = 1,
                .peer_addr_v6 = "::1",
                .peer_port = 55551,
                .local_addr_v6 = "::1",
                .local_port = 55553,
            },
        },
        .server_interface_count = 2,
        .server_interfaces = {
            {
                .meta = {
                    .interface_type = INTERFACE_G1
                },
                .local_port = 55552,
                .peer_count = 2,
                .peers = {
                    {
                        .peer_SAC = 16,
                        .peer_port = 55558,
                    },
                    {
                        .peer_SAC = 17,
                        .peer_port = 55563,
                    }
                },
            },
            {
                .meta = {
                    .interface_type = INTERFACE_G5,
                },
                .local_port = 55554,
                .peer_count = 1,
                .peers = {
                    {
                        .peer_SAC = 3,
                        .peer_port = 55555,
                    },
                },
            },
        }
    },
    {
        .SAC = 3,
        .element_type = ELEMENT_DBSM,
        .element_tag = "DBSM",
        .start_func = start_dbsm,
        .stop_func = stop_dbsm,
        .client_interface_count = 1,
        .client_interfaces = {
            {
                .meta = {
                    .interface_type = INTERFACE_G5,
                },
                .peer_SAC = 2,
                .peer_addr_v6 = "::1",
                .peer_port = 55554,
                .local_addr_v6 = "::1",
                .local_port = 55555,
            },
        },
        .server_interface_count = 1,
        .server_interfaces = {
            {
                .meta = {
                    .interface_type =  INTERFACE_G7,
                },
                .local_port = 55556,
                .peer_count = 1,
                .peers = {
                    {
                        .peer_SAC = 4,
                        .peer_port = 55557,
                    },
                },
            },
        }
    },
{
    .SAC = 4,
    .element_type = ELEMENT_RDF,
    .element_tag = "RDF",
    .start_func = start_rdf,
    .stop_func = stop_rdf,
    .client_interface_count = 2,
    .client_interfaces = {
        {
            .meta = {
                .interface_type = INTERFACE_G7,
            },
            .peer_SAC = 3,
            .peer_addr_v6 = "::1",
            .peer_port = 55556,
            .local_addr_v6 = "::1",
            .local_port = 55557,
        },
        {
            .meta = {
                .interface_type = INTERFACE_GAU,
            },
            .peer_addr_v6 = "::1",
            .peer_port = 5911,
            .local_addr_v6 = "::1",
            .local_port = 50002,
        },
    },
    .server_interface_count = 1,
    .server_interfaces = {
        {
            .meta = {
                .interface_type = INTERFACE_G1U,
            },
            .local_port = 50001,
            .peer_count = 2,
            .peers = {
                {
                    .peer_SAC = 16,
                    .peer_port = 50010,
                },
                {
                    .peer_SAC = 17,
                    .peer_port = 50011,
                },
            },
        },
    }
},
    {
        .SAC = 16,
        .element_type = ELEMENT_GSG,
        .element_tag = "GSG_010",
        .start_func = start_gsg,
        .stop_func = stop_gsg,
        .client_interface_count = 2,
        .client_interfaces = {
            {
                .meta = {
                    .interface_type = INTERFACE_G1,
                },
                .peer_SAC = 2,
                .peer_addr_v6 = "::1",
                .peer_port = 55552,
                .local_addr_v6 = "::1",
                .local_port = 55558,
            },
            {
                .meta = {
                    .interface_type = INTERFACE_G1U,
                },
                .peer_SAC = 4,
                .peer_addr_v6 = "::1",
                .peer_port = 50001,
                .local_addr_v6 = "::1",
                .local_port = 50010,
            },
        },
        .server_interface_count = 1,
        .server_interfaces = {
            {
                .meta = {
                    .interface_type = INTERFACE_GS1
                },
                .local_port = 55559,
                .peer_count = 1,
                .peers = {
                    {
                        .peer_SAC = 16,
                        .peer_port = 55560,
                    },
                },
            },
        }
    },
    {
        .SAC = 17,
        .element_type = ELEMENT_GSG,
        .element_tag = "GSG_011",
        .start_func = start_gsg,
        .stop_func = stop_gsg,
        .client_interface_count =2,
        .client_interfaces = {
            {
                .meta = {
                    .interface_type = INTERFACE_G1,
                },
                .peer_SAC = 2,
                .peer_addr_v6 = "::1",
                .peer_port = 55552,
                .local_addr_v6 = "::1",
                .local_port = 55563,
            },
            {
                .meta = {
                    .interface_type = INTERFACE_G1U,
                },
                .peer_SAC = 4,
                .peer_addr_v6 = "::1",
                .peer_port = 50001,
                .local_addr_v6 = "::1",
                .local_port = 50011,
            },
},
        .server_interface_count = 1,
        .server_interfaces = {
            {
                .meta = {
                    .interface_type = INTERFACE_GS1
                },
                .local_port = 55564,
                .peer_count = 1,
                .peers = {
                    {
                        .peer_SAC = 17,
                        .peer_port = 55565,
                    },
                },
            },
        }
    },
// {
//     .element_type = ELEMENT_ATN,
//     .element_tag = "ATN",
//     .start_func = NULL,
//     .stop_func = NULL,
//     .client_interface_count = 0,
//     .server_interface_count = 1,
//     .server_interfaces = {
//         {
//             .meta = {
//                 .interface_type = INTERFACE_GAU
//             },
//             .local_port = 5911,
//             .peer_count = 1,
//             .peers = {
//                 {
//                     .peer_SAC = 4,
//                     .peer_port = 50002,
//                 },
//             },
//         },
//     }
// },
};

static void sigint_handler(int signum) {
    atomic_store(&exit_flag, 1); // 设置退出标志


    for (int i = 0; i < elements_count; i++) {
        destroy_element_service(&elements[i]);
    }

    usleep(500000);


    log_info("ldacs corenet(PID: %u) exit...", getpid());
    //    kill(-getpid(), SIGINT);
    exit(0);
}

static void init_signal() {
    signal(SIGINT, sigint_handler);
    signal(SIGABRT, sigint_handler);
    signal(SIGQUIT, sigint_handler);
    signal(SIGTERM, sigint_handler);
    signal(SIGPIPE, SIG_IGN); // client close, server write will recv sigpipe
}

int opt_parse(int argc, char *const *argv) {
    int c;
    while ((c = getopt(argc, argv, "DS")) != -1) {
        switch (c) {
            case 'D': {
                direct_snp = TRUE;
                break;
            }
            case 'S': {
                is_dashboard = TRUE;
                break;
            }
            default: {
                return ERROR;
            }
        }
    }
    return OK;
}

static void usage(const char *executable) {
    printf("Usage: %s [-D direct_snp] [-S dashboard]\n",
           executable);
}

int main(int argc, char **argv) {
    log_init(LOG_DEBUG, "./log", "CN");
    init_signal();

    if (opt_parse(argc, argv) != OK) {
        usage(argv[0]);
        exit(ERROR);
    }

    if (is_dashboard) {
        init_dashboard_service();
    }

    for (int i = 0; i < elements_count; i++) {
        if (elements[i].start_func != NULL) {
            elements[i].start_func(&elements[i]);
        } else {
            cn_log_error(elements[i].element_tag, INTERFACE_UNDEFINED, "No profile");
        }
        usleep(500000);
    }
    input_service_t input_service;
    start_input_service(&input_service);

    while (!atomic_load(&exit_flag)) {
        sleep(1000); // 避免忙等待
    }

    return 0;
}
